/**
 * 
 */
package com.auz.datagenerator.publishing;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.logging.Logger;

/**
 * Class used to publish data to a file. The publisher, as any other one, can be paused and
 * unpaused, programatically preventing the publication of data. The data to be written is
 * defined in generics, and when writing the data, the <code>toString()</code> method is used.
 * @author Aurelien Bonnel
 */
public class FilePublisher<X> extends Thread implements IPublisher<X> {

	private Logger logger = Logger.getLogger("FilePublisher");
	
	private static final String DEFAULT_DELIMITER = ",\n";
	private String filename, delimiter;
	private FileOutputStream out;
	private boolean write = true;
	
	/**
	 * Constructor
	 * @param _filename - the filename the publisher writes to
	 */
	public FilePublisher(String _filename) {
		this(_filename, true);
	}
	
	/**
	 * Constructor
	 * @param _filename - the filename the publisher writes to
	 * @param _append - whether to append to a file or write to a fresh file
	 */
	public FilePublisher(String _filename, boolean _append) {
		this(_filename, true, DEFAULT_DELIMITER );
	}
	
	/**
	 * Constructor
	 * @param _filename - the filename the publisher writes to
	 * @param _delimiter - the delimiter used between data entries
	 */
	public FilePublisher(String _filename, String _delimiter) {
		this(_filename, true, _delimiter);
	}
	
	/**
	 * Constructor
	 * @param _filename - the filename the publisher writes to
	 * @param _append - whether to append to a file or write to a fresh file
	 * @param _delimiter - the delimiter used between data entries
	 */
	public FilePublisher(String _filename, boolean _append, String _delimiter) {
		this.filename = _filename;
		this.delimiter = _delimiter;
		try {
			out = new FileOutputStream(new File(filename), _append);
		} catch (FileNotFoundException e) {
			logger.severe("FilePublisher " + this.toString() + " couldn't find " + filename);
			write = false;
		}
		logger.info("FilePublisher " + this.toString() + " writing to " + filename);
	}
	
	/**
	 * Pause the publisher
	 */
	public void pause() {
		logger.finest("FilePublisher " + this.toString() + " paused");
		write = false;
	}

	/**
	 * Publish an entry
	 * @param _entry - the entry to publish to file
	 */
	public void publish(X _entry) {
		if(write) {
			logger.info("Publishing from " + this.toString() + ": " + _entry.toString());
			try {
				out.write(_entry.toString().getBytes());
				out.write(delimiter.getBytes());
			} catch (IOException e) {
				logger.severe("FilePublisher " + this.toString() + " couldn't write to " + filename);
				write = false;
			}
		}
	}

	/**
	 * Unpause the publisher
	 */
	public void unpause() {
		logger.finest("FilePublisher " + this.toString() + " resumed");
		write = true;
	}

	/**
	 * Stop the publisher. The file is released and made available for use.
	 */
	public void halt() {
		logger.info("Stopping FilePublisher " + this.toString());
		try {
			out.close();
		} catch (IOException e) {
			logger.severe("FilePublisher " + this.toString() + " couldn't be stopped");
			write = false;
		}
	}

	public void run() {}

}
